
<template>
  <div
    class="parameter-card h-full"
    :class="{
      'parameter-card--active': activeId === item.i,
      line: item.type === 2,
      border: hasBorder,
      flex:
        (item.table && item.table.tableType === 1) ||
        item.valueType === types.BOOLEAN,
      'parameter-card--error': item.error
    }"
  >
    <div
      v-if="item.type === 1"
      :class="{
        'h-full':
          item.valueType === types.STRING || item.valueType === types.HEX,
        'w-full':
          item.valueType === types.REFERENCE || item.valueType === types.BOOLEAN
      }"
    >
      <i
        v-if="closable"
        class="el-icon-close parameter-card__close"
        @click="() => removeItem(item.i)"
      />
      <div class="flex items-center">
        <span
          v-if="
            !(
              (item.table && item.table.tableType === 1) ||
              item.valueType === types.BOOLEAN
            )
          "
          class="parameter-card__title flex-1"
          :class="{
            'parameter-card__title--reference':
              item.valueType === types.REFERENCE
          }"
        >
          <i
            v-if="item.nullable != 1"
            style="
              color: #f56c6c;
              margin-right: 2px;
              position: absolute;
              top: 3px;
            "
            >*</i
          >
          <span v-ellipsis class="parameter-label w-9/10">{{
            item.label
          }}</span>
          <span>
            <i
              v-if="showReferenceIcon"
              class="cursor-pointer el-icon-position p-1 hover:text-blue-1 ml-2"
              @click.stop="$emit('newTab', item.table.id)"
            />
            <el-popover
              v-if="item.description && item.description != ''"
              placement="top-start"
              title
              width="280"
              trigger="hover"
              :content="item.description"
            >
              <template #reference>
                <i type="primary" class="el-icon-info" style="color: #74b0e5"
              /></template>
            </el-popover>
          </span>
        </span>
        <span
          v-if="
            item.table &&
            item.table.tableType !== 1 &&
            item.valueType === types.REFERENCE
          "
          class="parameter-card__number"
        >
          {{ referenceLength }}/{{ item.maxLength }}
        </span>
      </div>
      <el-form-item
        v-if="item.valueType === types.BOOLEAN"
        :prop="item.i"
        class="parameter-boolean"
      >
        <div class="w-full">
          <el-checkbox
            v-if="hasParam"
            v-model="item.paramValues"
            :disabled="disabled"
            @change="handleBooleanChange"
            ><span v-ellipsis class="parameter-label parameter-label--boolean">
              <el-popover
                v-if="item.description && item.description != ''"
                placement="top-start"
                title
                width="280"
                trigger="hover"
                :content="item.description"
              >
                <template #reference>
                  <i
                    type="primary"
                    class="el-icon-info ml-1"
                    style="color: #74b0e5"
                /></template>
              </el-popover>
              <span>{{ item.label }}</span></span
            ></el-checkbox
          >
          <el-checkbox
            v-else
            v-model="item.defaultValues"
            :disabled="disabled"
            @change="handleBooleanChange"
            ><span v-ellipsis class="parameter-label">
              <el-popover
                v-if="item.description && item.description != ''"
                placement="top-start"
                title
                width="280"
                trigger="hover"
                :content="item.description"
              >
                <template #reference>
                  <i
                    type="primary"
                    class="el-icon-info ml-1"
                    style="color: #74b0e5"
                /></template>
              </el-popover>
              <span>
                {{ item.label }}
              </span>
            </span>
          </el-checkbox>
        </div>
      </el-form-item>

      <template v-else-if="item.valueType === types.FILE">
        <el-form-item
          :prop="item.i"
          :rules="[{ required: isRequired, message: $t('flyparam.required2') }]"
        >
          <div v-ellipsis class="cursor-pointer" @click="handleSelectFile">
            <span
              :class="{
                'text-secondary': !fileSelected,
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
            >
              <i class="el-icon-document" />
              {{ fileLabel }}
            </span>
          </div>
        </el-form-item>
      </template>

      <template v-else-if="item.valueType === types.REFERENCE">
        <el-form-item
          :prop="item.i"
          :rules="[{ validator: validateReferenceLength, trigger: 'change' }]"
        >
          <div
            v-if="item.table && item.table.tableType === 1"
            class="text-center parameter-reference"
          >
            <button type="button" :disabled="disabled">
              <i class="el-icon-edit-outline mr-[10]" />
              <span
                v-ellipsis
                class="parameter-label parameter-label__reference hover:text-blue-1"
                @click="$emit('select-reference', item)"
                >{{ item.label }}</span
              >
              <el-popover
                v-if="item.description && item.description != ''"
                placement="top-start"
                title
                width="280"
                trigger="hover"
                :content="item.description"
              >
                <template #reference>
                  <i
                    type="primary"
                    class="el-icon-info ml-1"
                    style="color: #74b0e5"
                /></template>
              </el-popover>
              <i
                v-if="design && item.table && item.table.tableType === 1"
                class="el-icon-position cursor-pointer p-1 hover:text-blue-1 ml-2"
                @click.stop="$emit('newTab', item.table.id)"
              />
            </button>
          </div>

          <div
            v-else-if="item.table && item.table.tableType === 2"
            class="flex items-center"
          >
            <el-select
              v-model="item[propName]"
              class="el-select__reference"
              multiple
              :multiple-limit="item.maxLength"
              collapse-tags
              size="small"
            >
              <el-option
                v-for="item in referenceOptions"
                :key="item"
                :label="item"
                :value="item"
              />
            </el-select>
            <div v-if="!disabled" class="el-select-append">
              <button
                type="button"
                :disabled="disabled"
                class="el-button"
                @click="$emit('select-reference', item)"
              >
                {{ $t('flyparam.select') }}
              </button>
            </div>
          </div>

          <el-select
            v-else-if="hasParam"
            v-model="item.paramValues"
            v-loadmore="handleLoadMoreReference"
            multiple
            :disabled="
              disabled || (item.table ? item.table.tableType !== 3 : false)
            "
            :multiple-limit="item.maxLength"
            collapse-tags
            size="small"
            @visible-change="(visible) => fetchReferenceData(visible, true)"
            @click.native="$emit('select-reference', item)"
          >
            <el-option
              v-for="item in referenceValues"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
          <el-select
            v-else
            v-model="item.defaultValues"
            v-loadmore="handleLoadMoreReference"
            multiple
            :disabled="
              disabled || (item.table ? item.table.tableType !== 3 : false)
            "
            :multiple-limit="item.maxLength"
            collapse-tags
            size="small"
            @visible-change="(visible) => fetchReferenceData(visible, true)"
            @click.native="$emit('select-reference', item)"
          >
            <el-option
              v-for="item in referenceValues"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
      </template>

      <template v-else-if="item.valueType === types.TIME">
        <el-form-item
          :prop="item.i"
          :rules="[
            {
              required: !item.nullable && hasParam,
              message: this.$t('flyparam.required2')
            }
          ]"
        >
          <div
            class="flex items-center text-center"
            :class="{ 'input-append-container': showUndoButton }"
          >
            <el-time-picker
              v-if="hasParam"
              v-model="item.paramValues"
              :disabled="disabled"
              format="HH:mm:ss"
              value-format="HH:mm:ss"
              :placeholder="item.defaultValues"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <el-time-picker
              v-else
              v-model="item.defaultValues"
              :disabled="disabled"
              :format="item.formatter"
              :value-format="item.formatter"
              :placeholder="$t('flyparam.choose_time_tip')"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <div v-if="showUndoButton" class="input-append">
              <button
                type="button"
                class="el-button el-button--default"
                @click.stop="$emit('undo')"
              >
                <i class="el-icon-refresh-left" />
              </button>
            </div>
          </div>
        </el-form-item>
      </template>

      <template v-else-if="item.valueType === types.DATE">
        <el-form-item
          :prop="item.i"
          :rules="[
            { required: isRequired, message: this.$t('flyparam.required2') }
          ]"
        >
          <div
            class="flex items-center text-center"
            :class="{ 'input-append-container': showUndoButton }"
          >
            <el-date-picker
              v-if="hasParam"
              v-model="item.paramValues"
              :disabled="disabled"
              :format="item.formatter"
              type="date"
              :placeholder="item.defaultValues"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <el-date-picker
              v-else
              v-model="item.defaultValues"
              :disabled="disabled"
              :format="item.formatter"
              type="date"
              :placeholder="$t('flyparam.choose_time_tip')"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <div v-if="showUndoButton" class="input-append">
              <button
                type="button"
                class="el-button el-button--default"
                @click.stop="$emit('undo')"
              >
                <i class="el-icon-refresh-left" />
              </button>
            </div>
          </div>
        </el-form-item>
      </template>

      <template v-else-if="item.valueType === types.DATETIME">
        <el-form-item
          :prop="item.i"
          :rules="[
            { required: isRequired, message: this.$t('flyparam.required2') }
          ]"
        >
          <div
            class="flex items-center text-center"
            :class="{ 'input-append-container': showUndoButton }"
          >
            <el-date-picker
              v-if="hasParam"
              v-model="item.paramValues"
              :disabled="disabled"
              :format="item.formatter"
              type="datetime"
              :placeholder="item.defaultValues"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <el-date-picker
              v-else
              v-model="item.defaultValues"
              :value="form[item.i]"
              :disabled="disabled"
              :format="item.formatter"
              type="datetime"
              :placeholder="$t('flyparam.choose_time_tip')"
              size="small"
              style="width: 100%"
              @change="(value) => (form[item.i] = value)"
            />
            <div v-if="showUndoButton" class="input-append">
              <button
                type="button"
                class="el-button el-button--default"
                @click.stop="$emit('undo')"
              >
                <i class="el-icon-refresh-left" />
              </button>
            </div>
          </div>
        </el-form-item>
      </template>

      <template v-else-if="item.valueType === types.NUMBER">
        <div>
          <el-form-item
            :prop="item.i"
            :rules="[
              {
                required: isRequired,
                message: `${item.label} is required`,
                trigger: 'change'
              },
              {
                validator: validateNumber,
                trigger: 'change',
                maxLength: item.maxLength,
                minLength: item.minLength
              }
            ]"
          >
            <el-input
              :disabled="disabled"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              :maxlength="item.maxLength"
              :value="form[item.i]"
              size="small"
              @input="(val) => handleInput(val)"
            >
              <template #append>
                <el-button
                  v-if="showUndoButton"
                  icon="el-icon-refresh-left"
                  @click.stop="$emit('undo')"
              /></template>
            </el-input>
          </el-form-item>
        </div>
      </template>

      <template v-else-if="item.valueType === types.HEX">
        <!-- <span v-if="!disabled" class="parameter-card__number">{{ wordCount }}/{{ item.maxLength }}</span> -->
        <div style="height: calc(100% - 24px)">
          <el-form-item
            class="form-item__string"
            :prop="item.i"
            :rules="[
              {
                required: isRequired,
                message: `${item.label} is required`
              },
              { validator: validateHex, maxLength: item.maxLength }
            ]"
          >
            <el-input
              style="height: 100%"
              :disabled="disabled"
              show-word-limit
              :type="item.h > 2 ? 'textarea' : 'text'"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              :maxlength="item.maxLength"
              :value="form[item.i]"
              size="small"
              @input="handleHexInput"
            >
              <template #append>
                <el-button
                  v-if="showUndoButton"
                  icon="el-icon-refresh-left"
                  @click.stop="$emit('undo')"
              /></template>
            </el-input>
          </el-form-item>
        </div>
      </template>

      <template v-else>
        <!-- <span class="parameter-card__number">{{wordCount}}/{{item.maxLength}}</span> -->
        <div style="height: calc(100% - 24px)">
          <el-form-item
            class="form-item__string"
            :prop="item.i"
            :rules="[
              {
                required: isRequired,
                message: `${item.label} is required`,
                trigger: 'blur'
              },
              { validator: validateString, maxLength: item.maxLength }
            ]"
          >
            <el-input
              style="height: 100%"
              :disabled="disabled"
              show-word-limit
              :type="item.h > 2 ? 'textarea' : 'text'"
              :class="{
                default:
                  item.paramDefault && item.paramValues === item.defaultValues
              }"
              :maxlength="item.maxLength"
              :value="form[item.i]"
              size="small"
              @input="handleStringInput"
            >
              <template #append>
                <el-button
                  v-if="showUndoButton"
                  icon="el-icon-refresh-left"
                  @click.stop="$emit('undo')"
              /></template>
            </el-input>
          </el-form-item>
        </div>
      </template>
    </div>

    <div v-else>
      <i
        v-if="closable"
        class="el-icon-close parameter-card__close"
        @click="() => removeItem(item.i)"
      />
      <el-divider :content-position="alignment">
        <span>{{ item.title }}</span>
      </el-divider>

      <!-- <el-divider style="margin: 0;"></el-divider> -->
    </div>
  </div>
</template>

<script>
import { types, MAX_LENGTH } from '../constant.js'
import { isObjectBoolean } from '@/utils/index.js'
import { getReferenceEntryRecord } from '@/api/parameter'

function validateNumber(rule, value, callback) {
  if (value.length > 0) {
    if (!/^[+-]?((\d+(\.\d*)?)|(\.\d+))$/.test(value)) {
      return callback(
        new Error(
          this.$t('flyparam.invalid_input') +
            '(' +
            this.$t('flyparam.type_number') +
            ')'
        )
      )
    }
  }
  if (Number(value) > rule.maxLength) {
    return callback(new Error(this.$t('flyparam.max_number_exceeds')))
  }
  if (Number(value) < rule.minLength) {
    return callback(new Error(this.$t('flyparam.number_too_small')))
  }
  callback()
}

function validateHex(rule, value, callback) {
  if (value) {
    if (!/^[0-9a-fA-F]+$/.test(value)) {
      return callback(new Error(this.$t('flyparam.invalid_input')))
    }
    if (value.length > rule.maxLength) {
      return callback(new Error(this.$t('flyparam.length_exceeds')))
    }
  }

  callback()
}

function validateReferenceLength(rule, value, callback) {
  // if (this.item.table.tableType === 3) {
  //   if (this.item.defaultValues.length < 1) {
  //     return callback(new Error(this.$t('flyparam.required2')))
  //   }
  // }
  if (value) {
    const key = this.hasParam ? 'paramValues' : 'defaultValues'
    if (this.item[key].length > this.item.maxLength) {
      return callback(new Error(this.$t('flyparam.length_exceeds')))
    }

    if (
      this.hasParam &&
      this.item[key].length === 0 &&
      this.item.nullable === 0 &&
      this.item.table.tableType !== 1
    ) {
      return callback(new Error(this.$t('flyparam.required2')))
    }
  }
  callback()
}

function validateString(rule, value, callback) {
  if (value) {
    if (value.length > rule.maxLength) {
      return callback(new Error(this.$t('flyparam.length_exceeds')))
    }
  }
  callback()
}

export default {
  inheritAttrs: false,
  props: {
    design: {
      type: Boolean,
      default: false
    },
    item: {
      type: Object
    },
    form: {
      type: Object
    },
    activeId: {
      type: String
    },
    closable: {
      type: Boolean,
      default: true
    },
    editable: {
      type: Boolean
    },
    disabled: {
      type: Boolean
    },
    referenceDisabled: {
      type: Boolean
    },
    hasBorder: {
      type: Boolean,
      default: false
    },
    flex: {
      type: Boolean,
      default: false
    },
    hideTitle: {
      type: Boolean,
      default: false
    },
    templateId: {
      type: String
    },
    paramEdit: Boolean,
    showUndoButton: Boolean // 是否显示撤销按钮
  },

  data() {
    return {
      types,
      rules: {},
      validateHex: validateHex.bind(this),
      validateNumber: validateNumber.bind(this),
      validateReferenceLength: validateReferenceLength.bind(this),
      validateString: validateString.bind(this),
      referencePage: 1, // 查询引用类型数据表格的页码
      referenceValues: [], // 后端返回引用类型的数据表格,
      totalReferences: 1
    }
  },
  computed: {
    componentName() {
      return this.$parent.$options.name
    },
    hasParam() {
      return Object.hasOwnProperty.call(this.item, 'paramValues')
    },
    propName() {
      return this.hasParam ? 'paramValues' : 'defaultValues'
    },
    fileSelected() {
      if (this.hasParam) {
        return this.item.paramValues.length > 0
      } else {
        return this.item.defaultValues > 0
      }
    },
    wordCount() {
      if (this.form) {
        return this.form[this.item.i].length
      }
      return 0
    },
    referenceLength() {
      if (this.hasParam) {
        return this.item.paramValues && this.item.paramValues.length
      } else {
        return this.item.defaultValues && this.item.defaultValues.length
      }
    },
    showReferenceIcon() {
      return (
        this.item.valueType === types.REFERENCE &&
        this.design &&
        this.item.table &&
        this.item.table.tableType === 1
      )
    },
    fileLabel() {
      let value
      if (this.hasParam) {
        value = this.item.paramValues
      } else {
        value = this.item.defaultValues
      }
      if (!value) {
        if (this.disabled) {
          return ''
        } else {
          return this.$t('flyparam.choose_file_tip')
        }
      } else {
        return value
      }
    },
    isRequired() {
      return (
        this.item &&
        !this.item.nullable &&
        this.hasParam &&
        this.item.paramPermissionControl === 1
      )
    },
    // 引用类型下拉框已选中的值
    referenceOptions() {
      if (this.hasParam) {
        return this.item.paramValues
      }
      return this.item.defaultValues
    },
    alignment() {
      const alignment = {
        l: 'left',
        c: 'center',
        r: 'right'
      }

      return alignment[this.item.horizontalAlign]
    }
  },
  methods: {
    removeItem() {
      this.$emit('close', this.item.i)
    },

    handleLoadMoreReference() {
      this.referencePage++
      this.fetchReferenceData(true)
    },

    handleHexInput(val) {
      if (this.hasParam) {
        this.item.paramValues = val
      } else {
        this.item.defaultValues = val
      }
      this.form[this.item.i] = val
    },

    handleInput(val) {
      const value = val.replace(/[^-\d*\.\d+]/g, '')
      if (this.hasParam) {
        this.item.paramValues = value
      } else {
        this.item.defaultValues = value
      }
      this.form[this.item.i] = value
    },
    handleStringInput(val) {
      if (this.hasParam) {
        this.item.paramValues = val
      } else {
        this.item.defaultValues = val
      }
      this.form[this.item.i] = val
    },
    handleBooleanChange(val) {
      this.form[this.item.i] = val
    },
    handleSelectFile(item) {
      if (!this.disabled) {
        this.$emit('select-file', this.item.i)
        return
      }
    },
    fetchReferenceData(visible, triggerByDropDown) {
      if (visible) {
        if (triggerByDropDown) {
          this.referenceValues = []
          this.totalReferences = 1
          this.referencePage = 1
        }
        if (this.totalReferences <= this.referenceValues.length) {
          return
        }

        getReferenceEntryRecord(this.templateId, this.item.table.id, {
          pageNo: this.referencePage,
          pageSize: 10
        }).then((data) => {
          const value = data.items.map((item) => {
            return item.$label[0]
          })
          this.totalReferences = data.total
          this.referenceValues.push(...value)
        })
      }
    }
  }
}
</script>

<style scoped>
.parameter-card >>> .el-divider--horizontal {
  margin: 5px 0;
}
</style>

<style lang="scss" scoped>
$activeColor: #409eff;
@import '@/styles/mixin.scss';
@include parameterCard;
@include inputAppendButton;

::v-deep .default .el-input__inner {
  color: #cccccc;
}

::v-deep .el-form-item .default {
  color: #cccccc;
}

::v-deep .el-checkbox__label {
  line-height: 11px;
}

::v-deep .el-textarea__inner {
  height: 100%;
}

::v-deep .el-form-item__content {
  line-height: 30px;
}

::v-deep .el-input {
  // height: 30px !important;
}

::v-deep .form-item__string {
  height: 100%;

  .el-form-item__content {
    height: 85%;
  }
}

::v-deep .el-form-item__error {
  padding-top: 0;
}

.parameter-card {
  ::v-deep .el-select {
    height: auto;
  }

  @include elSelectAppend;
}

.parameter-label {
  display: inline-block;
  padding-left: 10px;
  line-height: 15px;

  &.parameter-lable--boolean {
    line-height: 10px;
  }
}

::v-deep .parameter-boolean {
  display: flex;

  .el-form-item__content {
    width: 100%;
  }

  .parameter-label {
    width: 100%;
  }

  .el-checkbox__label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
</style>
